﻿using MathNet.Numerics.LinearAlgebra.Double;
using innovations.ml.core.models;

namespace innovations.ml.core.solvers
{
    public class L_BFGS : Solver
    {
        public L_BFGS() : base() { }

        public override void Run(int numberOfLabels = 1)
        {
            Model.Solver = this;
            if (this.Model.GetType() == typeof(NeuralNetworkModel))
                RunNN(numberOfLabels);
            else
            {
                double epsg = 0.0000000001;
                double epsf = 0;
                double epsx = 0;
                int maxits = Iterations;
                alglib.minlbfgsstate state;
                alglib.minlbfgsreport rep;
                double[] tempTheta = Model.Theta.ToArray();
                alglib.minlbfgscreate(1, tempTheta, out state);
                alglib.minlbfgssetcond(state, epsg, epsf, epsx, maxits);
                alglib.minlbfgsoptimize(state, Model.ComputeCostAndGradient, null, null);
                alglib.minlbfgsresults(state, out tempTheta, out rep);
                Model.Theta = new DenseVector(tempTheta);
                Model.J = state.f;
            }
        }

        private void RunNN(int numberOfLabels = 1)
        {            
            alglib.multilayerperceptron mlp;
            alglib.mlpcreatec1(Model.X.ColumnCount, Model.MultiLevelMultiClassTheta[1].ColumnCount, numberOfLabels, out mlp);
        }
    }
}
